package org.rooster.chromosomeevaluator.rules;

import org.jgap.Gene;
import org.jgap.IChromosome;
import org.rooster.genetic.GeneIndex;
import org.rooster.genetic.GenericRule;
import org.rooster.manager.ResourceManager;
import org.rooster.manager.TaskManager;

import java.util.ArrayList;

/**
 * Created by IntelliJ IDEA. User: manorama Date: 6/5/12 Time: 9:11 PM To change
 * this template use File | Settings | File Templates.
 */
public class NoLunchBreakWithinLunchTimePenaltyRule implements GenericRule {

    private int weight = 1;
    private ArrayList<Integer> employeesWithNoLunchBeak = new ArrayList<Integer>();

    public NoLunchBreakWithinLunchTimePenaltyRule() {
    }

    public NoLunchBreakWithinLunchTimePenaltyRule(int weight) {
        this.weight = weight;
    }

    /**
     * If the employee is given lunch break within the correct time slot (one
     * hour) this method adds a bonus for it
     *
     * @param chromosome
     * @return the total bonus value
     */
    @Override()
    public double fitnessValueForRule(IChromosome chromosome) {
        int penalty = 1;
        int slotStartIndex = 0;
        int slotEndIndex = 0;
        int[][] lunchBreakAssignments = new int[ResourceManager.TOTAL_NO_OF_EMPLOYEES][TaskManager.NO_OF_SLOTS_FOR_LUNCH];

        Gene[] genes = chromosome.getGenes();
        for (int i = 0; i < TaskManager.NO_OF_SECTIONS; i++) {
            for (int j = TaskManager.lunchSlotStart; j <= TaskManager.lunchSlotEnd; j++) {
                slotStartIndex = GeneIndex.getTimeSlotStart(i, j);
                slotEndIndex = GeneIndex.getTimeSlotEnd(i, j);
                for (int k = slotStartIndex; k <= slotEndIndex; k++) {
                    lunchBreakAssignments[(Integer) genes[k].getAllele() - 1][j - TaskManager.lunchSlotStart] = 1;
                }
            }


        }
        for (int i = 0; i < lunchBreakAssignments.length; i++) {
            if (noLunchBreakGiven(lunchBreakAssignments[i])) {
                penalty++;
                employeesWithNoLunchBeak.add(i+1);
            }
        }
        return 1.0 /(penalty * weight);
    }

    @Override
    public int getWeight() {
        return weight;
    }

    @Override
    public void setWeight(int value) {
        this.weight = value;
    }

    private boolean noLunchBreakGiven(int[] lunchBreakAssignment) {
        int slotCount = 0;
        for (int i = 0; i < lunchBreakAssignment.length; i++) {
            if (lunchBreakAssignment[i] == 0) {
                slotCount++;
            } else if (slotCount < TaskManager.LUNCH_DURATION_IN_NO_OF_SLOTS) {
                slotCount = 0;
            }
        }
        if (slotCount >= TaskManager.LUNCH_DURATION_IN_NO_OF_SLOTS) {
                return false;
            }

        return true;
    }

    /**
     * @return the employeesWithNoLunchBeak
     */
    public ArrayList<Integer> getEmployeesWithNoLunchBeak() {
        return employeesWithNoLunchBeak;
    }
}
